<template>
	<div class="audio-check">
		<div class="title">麦克风输入设备确认</div>

		<div class="flex"> 
			<div class="left">
				<div class="sub-title">选择输入设备</div>
				<el-select v-model="selectedDevice" placeholder="请选择" style="width: 2.4rem; margin-bottom: 24px">
					<el-option
						v-for="device in audioDevices"
						:key="device.deviceId"
						:label="device.label || `Device ${device.deviceId}`"
						:value="device.deviceId">
					</el-option>
				</el-select>
				
			</div>
			<div class="right">
				<div class="sub-title">测试麦克风</div>
				<div class="flex-aic">
					<span class="iconfont icon-maikefeng" style="font-size: 24px;"></span>
					<!--音量大小显示-->
					<div class="volume-wapper">
						<div class="volume" :style="{width: `${volume}%`}"></div>
					</div>
				</div>
			</div>
		</div>
		<p>在测评的过程中，请尽量做到吐字清晰讲普通话，背景声音干净，这样收集到的语音数据分析的数据更准确。</p>


	</div>
</template>
<script setup>
import {ref, onMounted, onUnmounted, watch} from 'vue'

// 音频输入设备列表
const audioDevices = ref([])
const selectedDevice = ref(null)

// 音量大小 0-100
const volume = ref(0)



// 音频相关变量
let audio_context = null
let analyser = null
let microphone = null
let data_array = null
let animation_id = null
let media_stream = null



//获取麦克风列表
const getAudioInputs = async () => {
	try {
		const devices = await navigator.mediaDevices.enumerateDevices()
		audioDevices.value = devices.filter(device => device.kind === 'audioinput')
		if (audioDevices.value.length > 0) {
			selectedDevice.value = audioDevices.value[0].deviceId
		}
	} catch (error) {
		console.error('Error accessing audio devices:', error)
	}
}

// 开始音频检测
const start_audio_detection = async () => {
	try {
		// 停止之前的检测
		stop_audio_detection()
		
		// 获取音频流
		media_stream = await navigator.mediaDevices.getUserMedia({
			audio: {
				deviceId: selectedDevice.value ? { exact: selectedDevice.value } : undefined
			}
		})
		
		// 创建音频上下文
		audio_context = new (window.AudioContext || window.webkitAudioContext)()
		analyser = audio_context.createAnalyser()
		microphone = audio_context.createMediaStreamSource(media_stream)
		
		// 配置分析器
		analyser.fftSize = 256
		const buffer_length = analyser.frequencyBinCount
		data_array = new Uint8Array(buffer_length)
		
		// 连接音频节点
		microphone.connect(analyser)
		
		// 开始分析音量
		analyze_volume()
		
	} catch (error) {
		console.error('Error accessing microphone:', error)
	}
}

// 分析音量
const analyze_volume = () => {
	if (!analyser || !data_array) return
	
	// 获取频域数据
	analyser.getByteFrequencyData(data_array)
	
	// 计算平均音量
	let sum = 0
	for (let i = 0; i < data_array.length; i++) {
		sum += data_array[i]
	}
	const average = sum / data_array.length
	
	// 将音量转换为百分比 (0-100)
	volume.value = Math.min(100, Math.round((average / 255) * 100))
	

	
	// 继续下一帧分析
	animation_id = requestAnimationFrame(analyze_volume)
}



// 停止音频检测
const stop_audio_detection = () => {
	if (animation_id) {
		cancelAnimationFrame(animation_id)
		animation_id = null
	}
	
	if (media_stream) {
		media_stream.getTracks().forEach(track => track.stop())
		media_stream = null
	}
	
	if (audio_context) {
		audio_context.close()
		audio_context = null
	}
	
	analyser = null
	microphone = null
	data_array = null
	volume.value = 0
	

}

// 监听设备变化，重新开始检测
watch(selectedDevice, (new_device) => {
	if (new_device) {
		start_audio_detection()
	}
})

onMounted(async () => {
	await getAudioInputs()
	// 获取设备列表后自动开始检测
	if (selectedDevice.value) {
		start_audio_detection()
	}
})

onUnmounted(() => {
	stop_audio_detection()
})
</script>
<style scoped lang="scss">
.title{
	font-size: 20px;
	margin-top: 40px;
	margin-bottom: 24px;
}
.sub-title{
	font-size: 16px;
	margin-bottom: 12px;
}
.left{
	margin-right: 104px;
}

.volume-wapper{
	width: 305px;
	height: 6px;
	border-radius: 3px;
	overflow: hidden;
	background: #D8D8D8;
	margin-left: 12px;
	.volume{
		height: 100%;
		background: #29CB41;
		border-radius: 3px;
		transition: width 0.1s ease;
	}
}

.audio-check{
	border-bottom: 1px solid #fff;
	padding-bottom: 40px;
}
</style>

<style lang="scss" scoped>
@use '@/styles/variables.scss' as *;
:deep(.el-select__wrapper){
	background: $content-bg-color !important;
	border-color: #DCDCDC !important;
}
:deep(.el-select__placeholder) {
	color: #fff !important;
}
</style>